﻿namespace DataStructure;

public class ArrayMap
{
    static void Main(string[] args)
    {
        Console.WriteLine("array1D: ");
        int[] array1D = new int[8] //8
        { 1, 2, 3, 4, 5, 6, 7, 8, };
        //array1D[i]：前面有i个元素。
        //To array2D[u,v]：u=i/Cols, v=i%Col
        //To array3D[u,v,w]: u=i/(Rows*Cols), v=i%(Rows*Cols)/Cols, w=i%Cols
        //To arraynD[j1,j2,...,jn]: jk=i%(bk*...*bn)/b(k+1)*...*bn, k=1,...,n       
        //Print(array1D);
        array1D.Print();

        Console.WriteLine("array2D: ");
        int[,] array2D = new int[2, 4] //2*4
        {
            { 10, 20, 30, 40, },
            { 50, 60, 70, 80, },
        };
        //array2D[u, v]：前面有（u* Cols+v）个元素，0 <= v < Cols
        //To array1D[i]：i = u * Cols + v
        Print(array2D);

        Console.WriteLine("array3D: ");
        int[,,] array3D = new int[2, 2, 2] //2*2*2
        {
           {
                { 100, 200, },
                { 300, 400, },
           },

           {
                { 500, 600, },
                { 700, 800, },
           },
        };
        //array3D[u,v,w]：前面有（u*Rows*Cols+v*Cols+w）个元素，0<=v<Rows，0<=w<Cols
        //To array1D[i]：i=u*Rows*Cols+v*Cols+w  
        Print(array3D);

        int[][] jaggedArray = new int[3][]
        {
            //请注意：不能从元素初始化中省略 new 运算符，因为不存在元素的默认初始化
            //交错数组是数组的数组，因此其元素为引用类型且被初始化为 null。
            new[] { 1, 2, 3, },
            new[] { 4, 5, },
            new[] { 6, 7, 8, },
        };

        //可以混合使用交错数组和多维数组。下面声明和初始化一个包含大小不同的三个二维数组元素的一维交错数组。
        int[][,] mixedjaggedArray = new int[3][,] //
        {

            new int[,] { {1,3}, {5,7} },
            new int[,] { {0,2}, {4,6}, {8,10} },
            new int[,] { {11,22,33}, {99,88,77} }
        };

        Console.WriteLine($"维数：{array1D.Rank}\t\t个数：{array1D.Length}");
        Console.WriteLine($"维数：{array2D.Rank}\t\t个数：{array2D.Length}");
        Console.WriteLine($"维数：{array3D.Rank}\t\t个数：{array3D.Length}");
        Console.WriteLine($"维数：{jaggedArray.Rank}\t\t个数：{jaggedArray.Length}"); //方法 Length 返回包含在交错数组中的数组的数目。 
        Console.WriteLine($"维数：{mixedjaggedArray.Rank}\t\t个数：{mixedjaggedArray.Length}");

        ////copy from 2d to 1d       
        //for (int i = 0; i < array1D.Length; i++)
        //{
        //    int u = i / array2D.GetLength(1);
        //    int v = i % array2D.GetLength(1);
        //    array1D[i] = array2D[u, v];
        //    Console.WriteLine(array1D[i]);
        //}

        ////copy from 3d to 1d
        //for (int i = 0; i < array1D.Length; i++)
        //{
        //    int u = i / (array3D.GetLength(0) * array3D.GetLength(1));
        //    int v = i % (array3D.GetLength(0) * array3D.GetLength(1)) / array3D.GetLength(2);
        //    int w = i % array3D.GetLength(2);
        //    array1D[i] = array3D[u, v, w];
        //    Console.WriteLine(array1D[i]);
        //}

        //copy from 1d to 2d
        for (int i = 0; i < array2D.GetLength(0); i++)
        {
            for (int j = 0; j < array2D.GetLength(1); j++)
            {
                int s = i * array2D.GetLength(1) + j;
                array2D[i, j] = array1D[s];
                Console.WriteLine(array2D[i, j]);
            }
        }

        //copy from 1d to 3d
        for (int i = 0; i < array3D.GetLength(0); i++)
        {
            for (int j = 0; j < array3D.GetLength(1); j++)
            {
                for (int k = 0; k < array3D.GetLength(2); k++)
                {
                    int s = i * array3D.GetLength(1) * array3D.GetLength(2) + j * array3D.GetLength(2) + k;
                    array3D[i, j, k] = array1D[s];
                    Console.WriteLine(array3D[i, j, k]);
                }
            }
        }
    }

    //从1维映射到n维，动态规划算法
    public static void CopyArrayFrom1dToNd(Array array1d, Array arrayNd)
    {
        int N = arrayNd.Rank; //N：目标数组的维数。

        int[] T = new int[N]; //T：存储目标数组对应元素各个下标的计算表达式分母值。
        T[N - 1] = 1; //求最后一个下标时，分母值为1；
        for (int k = N - 2; k >= 0; k--)
        {
            T[k] = arrayNd.GetLength(k + 1) * T[k + 1];
        }

        for (int i = 0; i < array1d.Length; i++)
        {
            int[] J = new int[N]; //J：目标数组对应元素的下标数组，存储该元素的各维的下标值。
            for (int k = 0; k < N; k++)
            {
                J[k] = i % (arrayNd.GetLength(k) * T[k]) / T[k];
            }

            arrayNd.SetValue(array1d.GetValue(i), J);
        }
    }

    //从n维映射到1维，动态规划算法
    public static void CopyArrayFromNdTo1d(Array arrayNd, Array array1d)
    {
        int N = arrayNd.Rank; //N：目标数组的维数。

        int[] T = new int[N]; //T：存储目标数组对应元素各个下标的计算表达式分母值。
        T[N - 1] = 1; //求最后一个下标时，分母值为1；
        for (int k = N - 2; k >= 0; k--)
        {
            T[k] = arrayNd.GetLength(k + 1) * T[k + 1];
        }

        for (int i = 0; i < array1d.Length; i++)
        {
            int[] J = new int[N]; //J：目标数组对应元素的下标数组，存储该元素的各维的下标值。
            for (int k = 0; k < N; k++)
            {
                J[k] = i % (arrayNd.GetLength(k) * T[k]) / T[k];
            }

            array1d.SetValue(arrayNd.GetValue(J), i);
        }
    }

    public static void Print(Array arrayNd)
    {
        int N = arrayNd.Rank;
        int[] lens = new int[N - 1];
        int p = 1;
        for (int i = 1; i < N; i++)
        {
            lens[i - 1] = arrayNd.GetLength(i);
            p = p * lens[i - 1];
        }

        if (N == 1)
        {
            foreach (var item in arrayNd)
            {
                Console.Write(item + " ");
            }
            Console.WriteLine();
        }
        else
        {
            object[] arr = new object[arrayNd.Length];
            CopyArrayFromNdTo1d(arrayNd, arr);

            for (int i = 0; i < arrayNd.GetLength(0); i++)
            {
                Array array = Array.CreateInstance(typeof(object), lens);

                ArraySegment<object> segment = new ArraySegment<object>(arr, i * p, p);
                CopyArrayFrom1dToNd(segment.ToArray(), array);

                Console.WriteLine(i + ", ");
                Print(array);
            }
        }
    }
}
